package cz.mff.curreco.model;

import java.util.ArrayList;

public class MoneyItem {
	
	private int id;
	private int type;
	private String countryCode;
	private String officialName;
	private int amount;
	private String currencySymbol;
	private String pictureFrontPath;
	private String pictureBackPath;
	private ArrayList<Float> circularDescriptor;
	private ArrayList<Float> fatCircularDescriptor;
	
	public MoneyItem(String officialName, int amount, String currencySymbol, String countryCode, String pictureFrontPath, String pictureBackPath) {
		this.circularDescriptor = new ArrayList<Float>();
		this.fatCircularDescriptor = new ArrayList<Float>();
		this.officialName = officialName;
		this.amount = amount;
		this.currencySymbol = currencySymbol;
		this.countryCode = countryCode;
		this.setPictureFrontPath(pictureFrontPath);
		this.setPictureBackPath(pictureBackPath);
		
	}

	//----- GETTERS/SETTERS ----------------------------------------------------------	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public String getCountryCode() {
		return countryCode;
	}

	public void setCountryCode(String countryCode) {
		this.countryCode = countryCode;
	}

	public String getOfficialName() {
		return officialName;
	}

	public void setOfficialName(String officialName) {
		this.officialName = officialName;
	}

	public int getAmount() {
		return amount;
	}

	public void setAmount(int amount) {
		this.amount = amount;
	}

	public String getCurrencySymbol() {
		return currencySymbol;
	}

	public void setCurrencySymbol(String currencySymbol) {
		this.currencySymbol = currencySymbol;
	}	

	public String getPictureFrontPath() {
		return pictureFrontPath;
	}

	public void setPictureFrontPath(String pictureFrontPath) {
		this.pictureFrontPath = pictureFrontPath;
	}

	public String getPictureBackPath() {
		return pictureBackPath;
	}

	public void setPictureBackPath(String pictureBackPath) {
		this.pictureBackPath = pictureBackPath;
	}
	
	// -------------------------------------------------------------------------------
	
	//Setter for descriptor
	public void setCircularDescriptor(String value)
	{
		String []splits = value.split(" ");
		for(int i = 0;i<splits.length;i++)
		{
			circularDescriptor.add(Float.parseFloat(splits[i]));			
		}
	}
	
	public void setCircularDescriptorByValue(ArrayList<Float> input)
	{		
		circularDescriptor = input;
	}
	
	//Getter for descriptor
	public String getCircularDescriptor()
	{
		StringBuilder result = new StringBuilder();
		for(int i = 0;i<circularDescriptor.size();i++)
		{
			result.append(circularDescriptor.get(i));
			if(i<circularDescriptor.size()-1)
			{
				result.append(" ");
			}
		}
		return result.toString();
	}
	
	public String getFatCircularDescriptor()
	{
		StringBuilder result = new StringBuilder();
		for(int i = 0;i<fatCircularDescriptor.size();i++)
		{
			result.append(fatCircularDescriptor.get(i));
			if(i<fatCircularDescriptor.size()-1)
			{
				result.append(" ");
			}
		}
		return result.toString();		
	}
	
	public void setFatCircularDescriptor(String value)
	{
		String []splits = value.split(" ");
		for(int i = 0;i<splits.length;i++)
		{
			fatCircularDescriptor.add(Float.parseFloat(splits[i]));			
		}		
	}
	
	public void setFatCircularDescriptorByValue(ArrayList<Float> input)
	{		
		fatCircularDescriptor = input;
	}
	
	//Gets distance between two descriptors
	//Distance is sum of diferences in circular descriptors
	public double getDistance(MoneyItem second)
	{
		if(this.circularDescriptor.size() != second.circularDescriptor.size())
		{
			System.out.println("Delka deskriptoru nesouhlasi");
			System.out.println("Deskriptor vlozene (delka): " + this.circularDescriptor.size());
			System.out.println("Deskriptor porovnavane (delka): " + second.circularDescriptor.size());
			//Size of circular descriptor doesnt match
			return Float.MAX_VALUE;			
		}
		else
		{
			double totalDiff = 0;
			double deviation = circularDescriptor.get(0)/second.circularDescriptor.get(0);
			
			for (int i=0;i<circularDescriptor.size();i++)
			{
				double a = circularDescriptor.get(0);
				double b = second.circularDescriptor.get(0);
				totalDiff +=  Math.abs(a-b*deviation);
			}
			return totalDiff;
		}
		
	}
	//Compares this moneyItem with all other descriptors and gets best candidate for result
	//If the distance is more then paramether treshold returns null
	public MoneyItem getMostResemble(ArrayList<MoneyItem> candidates, float treshold)
	{
		System.out.println("Now computing difference according to simple circles");
		double bestMatchDistance = Float.MAX_VALUE - 1;
		MoneyItem bestMatchMoneyItem = null;
		if(candidates == null)
		{
			System.out.println("Descriptors from xml not loaded");			
		}

		if (candidates==null)
			return null;

		for(int i=0;i<candidates.size();i++)
		{
			System.out.println("now computing: " + candidates.get(i).getOfficialName());
			
			double actDistance = this.getDistance(candidates.get(i));
			System.out.println("Hodnota: " + candidates.get(i).getAmount() + ", vzdalenost: " + actDistance);
			if(actDistance < bestMatchDistance)
			{
				bestMatchDistance = actDistance;
				bestMatchMoneyItem = candidates.get(i);				
			}			
		}
		if(bestMatchDistance < treshold)
		{
			return bestMatchMoneyItem;
		}
		else
		{		
			return null;
		}
	}
	
	public MoneyItem getMostResembleByFatCircles(ArrayList<MoneyItem> candidates, float treshold)
	{
		System.out.println("Now computing difference according to fat circles");
		double bestMatchDistance = Float.MAX_VALUE - 1;
		MoneyItem bestMatchMoneyItem = null;
		
		for(int i=0;i<candidates.size();i++)
		{
			System.out.println("now computing: " + candidates.get(i).getOfficialName());
			
			double actDistance = this.getFatDistance(candidates.get(i));
			System.out.println("Hodnota: " + candidates.get(i).getAmount() + ", vzdalenost: " + actDistance);
			if(actDistance < bestMatchDistance)
			{
				bestMatchDistance = actDistance;
				bestMatchMoneyItem = candidates.get(i);				
			}			
		}
		if(bestMatchDistance < treshold)
		{
			return bestMatchMoneyItem;
		}
		else
		{		
			return null;
		}
	}
	
	public double getFatDistance(MoneyItem second)
	{
		if(this.fatCircularDescriptor.size() != second.fatCircularDescriptor.size())
		{
			System.out.println("Delka deskriptoru nesouhlasi");
			System.out.println("Deskriptor vlozene (delka): " + this.fatCircularDescriptor.size());
			System.out.println("Deskriptor porovnavane (delka): " + second.fatCircularDescriptor.size());
			//Size of circular descriptor doesnt match
			return Float.MAX_VALUE;			
		}
		else
		{
			float firstBlackA = fatCircularDescriptor.get(0);
			float firstBlackB = second.fatCircularDescriptor.get(0);
			
			double counter = 0;		
			for(int i=1;i<fatCircularDescriptor.size();i++)
			{
				float secondBlackA = fatCircularDescriptor.get(i);
				float secondBlackB = second.fatCircularDescriptor.get(i);				
				double value = (secondBlackA + 1)/(firstBlackA + 1) - (secondBlackB + 1)/(firstBlackB + 1);
				System.out.println("difference in circle = " + value);
				if(value < 0)
				{
				value = (-1) * value; 
				}
			counter += value;
			}
			return counter;
		}
		
	}
	
	
	
}
